package org.wupgateway.config;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.wupgateway.utils.JWTTokenUtil;
import reactor.core.publisher.Mono;

@Component
public class GlobalAuthenticationFilter implements GlobalFilter, Ordered {
	@Override
	/**
	 * 重写filter方法，实现网关过滤器
	 * @param exchange 服务器网络交换对象，包含请求和响应信息
	 * @param chain 网关过滤器链，用于传递请求到下一个过滤器
	 * @return Mono<Void> 表示异步操作的结果
	 */
	public Mono<Void> filter(
		ServerWebExchange exchange,
		// 服务器网络交换对象
		GatewayFilterChain chain) {  // 网关过滤器链
		// 从交换对象中获取请求对象
		ServerHttpRequest request = exchange.getRequest();
		// 获取请求路径
		String path = request
			.getPath()
			.value();
		
		// WebSocket握手请求放行：如果是升级为websocket，则跳过鉴权
		String upgrade = request
			.getHeaders()
			.getFirst("Upgrade");
		if (upgrade != null && "websocket".equalsIgnoreCase(upgrade)) {
			return chain.filter(exchange);
		}
		
		// 不需要验证token的路径，直接放行
		if (path.contains("/login") || path.contains("/register")) {
			return chain.filter(exchange);
		}
		
		// 获取token和key
		String token = request
			.getHeaders()
			.getFirst("Authorization");
		String key = request
			.getHeaders()
			.getFirst("Key");
		
		if (token == null || ! token.startsWith("Bearer ")) {
			exchange
				.getResponse()
				.setStatusCode(HttpStatus.UNAUTHORIZED);
			return exchange
				.getResponse()
				.setComplete();
		}
		
		// 验证token
		token = token.substring(7);
		boolean isValid = JWTTokenUtil.validateToken(
			token,
			key);
		
		if (! isValid) {
			exchange
				.getResponse()
				.setStatusCode(HttpStatus.UNAUTHORIZED);
			return exchange
				.getResponse()
				.setComplete();
		}
		
		return chain.filter(exchange);
	}
	
	/**
	 * 获取组件的执行顺序 该方法用于确定组件在加载或执行时的优先级，返回值越小表示优先级越高
	 *
	 * @return 返回组件的执行顺序值，此处返回-100表示该组件具有较高优先级
	 */
	@Override
	public int getOrder() {
		return - 100;  // 返回执行顺序值-100，表示该组件具有较高的优先级
	}
}
